<?php
namespace App\Logic\Spider;

use GuzzleHttp\Client;
use GuzzleHttp\Promise;
use Psr\Http\Message\ResponseInterface;
use GuzzleHttp\Pool;
use GuzzleHttp\Psr7\Request;
use Illuminate\Support\Facades\Storage;
use QL\QueryList;
class CrawlAsin
{
    public static function matchAsin($url,$asin,$outPutFile,$failFileName,$asinChar){
        $client = new Client([
            'timeout' => 5,
            'cookies' => true,
            'base_uri' => $url,
            'headers'=>['User-Agent' => array_random(self::$_userAgent)],
        ]);
        try{
            $response = $client->get($asin);
            $body = $response->getBody()->getContents();
            if(str_contains((string)$body, $asinChar)){
                $ql = QueryList::html($body);
                $resp = $ql->find('#acrPopover')->attr('title');
                $ql->destruct();
                Storage::disk('public')->append($outPutFile,$asin.' : '.(empty($resp)?'no review':$resp));
            }
        }catch(\Exception $e){
//            if($e->getCode() == 503 ){
//                Storage::disk('public')->append($failFileName, $asin.$e->getMessage());
//            }
        }
    }

    public static function matchAsinAsync($url,$asin,$outPutFile,$failFileName,$asinChar){
        $client = new Client([
            'timeout' => 5,
            'cookies' => true,
            'base_uri' => $url,
            'headers'=>['User-Agent' => array_random(self::$_userAgent)],
        ]);
        $client->getAsync($asin)->then(
            function (ResponseInterface $response) use ($outPutFile,$asin,$asinChar){
                $body = $response->getBody()->getContents();
                if(str_contains((string)$body,$asinChar)){
                    $ql = QueryList::html($body);
                    $resp = $ql->find('#acrPopover')->attr('title');
                    $ql->destruct();
                    Storage::disk('public')->append($outPutFile,$asin.' : '.(empty($resp)?'no review':$resp));
                }
            },
            function (\Exception $e) use ($failFileName,$asin){
                if($e->getCode() == 503 ){
                    Storage::disk('uploads')->append($failFileName, $asin);
                }
            }
        )->wait();
    }

    public static function matchReviewMulti($url,$asin,$outPutFile,$failFileName){
        $client = new Client([
            'timeout' => 5,
            'cookies' => true,
            'base_uri' => $url,
        ]);
        try{
            $promises = [
                1 => $client->getAsync($asin.'/ref=cm_cr_arp_d_viewopt_sr',
                    [
                        'query' => 'formatType=current_format&filterByStar=one_star',
                        'headers'=>['User-Agent' => array_random(self::$_userAgent)],
                    ]),
                2 => $client->getAsync($asin.'/ref=cm_cr_arp_d_viewopt_sr',
                    [
                        'query' => 'formatType=current_format&filterByStar=two_star',
                        'headers'=>['User-Agent' => array_random(self::$_userAgent)],
                    ]),
                3 => $client->getAsync($asin.'/ref=cm_cr_arp_d_viewopt_sr',
                    [
                        'query' => 'formatType=current_format&filterByStar=three_star',
                        'headers'=>['User-Agent' => array_random(self::$_userAgent)],
                    ]),
                4 => $client->getAsync($asin.'/ref=cm_cr_arp_d_viewopt_sr',
                    [
                        'query' => 'formatType=current_format&filterByStar=four_star',
                        'headers'=>['User-Agent' => array_random(self::$_userAgent)],
                    ]),
                5 => $client->getAsync($asin.'/ref=cm_cr_arp_d_viewopt_sr',
                    [
                        'query' => 'formatType=current_format&filterByStar=five_star',
                        'headers'=>['User-Agent' => array_random(self::$_userAgent)],
                    ])
            ];
            $results = Promise\unwrap($promises);
			sleep(10);
            $temp = [];
			foreach($results as $k=>$res){
				$body = $res->getBody()->getContents();
				$ql = QueryList::html($body);
				$resp = $ql->find('#cm_cr-review_list>div>span:first')->text();
				if(starts_with($resp,'Showing')){
					$temp[$k] = explode(' ',$resp)[3];
				}else{
					$temp[$k] = 0;
				}
				$ql->destruct();
			}
			$sum1 = collect($temp)->sum();
			$sum2 = collect($temp)->map(function ($k,$v){
				return $k * $v;
			})->sum();
			$s = $sum1 > 0 ? round($sum2/$sum1,1):0;
			Storage::disk('public')->append($outPutFile, $asin.' '.$s.' out of 5 stars');
        }catch(\Exception $e){
            $e->getCode() == 503 && Storage::disk('uploads')->append($failFileName, $asin);
        }
    }

    public static function proxyIp()
    {
        set_time_limit(0);
        ini_set('memory_limit','512M');
        $client = new Client(['timeout' => 5,
                              'cookies' => true,
                              'base_uri' => 'http://www.xicidaili.com/',
                              'headers'=>['User-Agent' => array_random(self::$_userAgent)],
        ]);
        $requests = function ($num){
            for($i = 1;$i <= $num; $i++){
                yield new Request('GET', 'nn/'.$i);
            }
        };
        $pool = new Pool($client,$requests(1),[
            'concurrency' => 5,
            'fulfilled' => function(ResponseInterface $response, $index) {
                $body = $response->getBody()->getContents();
                $ql = QueryList::rules(['ip' => ['td:eq(1)','text'],'port' => ['td:eq(2)','text']]);
                $ql->html($body)->range('#ip_list tr:gt(1)')->query()->getData(function($item){
                    return self::checkProxyIp($item['ip'].':'.$item['port']);
                })->all();
                $ql->destruct();
            },
            'rejected' => function ($reason, $index) {

            },
        ]);
        $promise = $pool->promise();
        $promise->wait();
    }

    public static function checkProxyIp($asin){
        $ch = curl_init();
//        curl_setopt($ch, CURLOPT_COOKIEJAR, "cookie.txt");
//        curl_setopt($ch, CURLOPT_COOKIEFILE, "cookie.txt");
//        curl_setopt($ch,CURLOPT_PROXY,"ip:port or http://ip:port");//使用代理访问 1
//        curl_setopt($ch, CURLOPT_PROXYAUTH, CURLAUTH_BASIC); //代理认证模式
//        curl_setopt($ch,CURLOPT_PROXYUSERPWD,"username:password");//代理认证帐号
//        curl_setopt($ch,CURLOPT_PROXYTYPE,CURLPROXY_HTTP);//使用http代理模式，SOCKS5代理模式 ：CURLPROXY_SOCKS5,Without a scheme prefix,can be used to specify
//        curl_setopt($ch,CURLOPT_URL,"https://www.baidu.com");//获取内容
        curl_setopt($ch,CURLOPT_URL,"https://www.amazon.com/dp/$asin");//获取内容
        curl_setopt($ch,CURLOPT_RETURNTRANSFER,1);//返回数据流，不直接输出
        curl_setopt($ch, CURLOPT_USERAGENT, array_random(self::$_userAgent));
        curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
        curl_setopt($ch, CURLOPT_VERBOSE, true);
        curl_setopt($ch,CURLOPT_HEADER,1);//获取头信息
        curl_setopt($ch,CURLOPT_TIMEOUT,5);//超时时长，单位秒
        curl_exec($ch);
        $rtn = curl_getinfo($ch,CURLINFO_HTTP_CODE);
        curl_close($ch);
        Storage::disk('public')->append('proxy/proxy.txt',$rtn.':'.$asin);
        return $rtn == 200;
    }

    public static function test(){
        $body=<<<STR
<table id="ip_list">
    <tr>
      <th class="country">国家</th>
      <th>IP地址</th>
      <th>端口</th>
      <th>服务器地址</th>
      <th class="country">是否匿名</th>
      <th>类型</th>
      <th class="country">速度</th>
      <th class="country">连接时间</th>
      <th width="8%">存活时间</th>
      
      <th width="20%">验证时间</th>
    </tr>
  
    <tr class="odd">
      <td class="country"><img src="http://fs.xicidaili.com/images/flag/cn.png" alt="Cn" /></td>
      <td>110.87.104.153</td>
      <td>8118</td>
      <td>
        <a href="/2018-08-01/fujian">福建厦门</a>
      </td>
      <td class="country">高匿</td>
      <td>HTTPS</td>
      <td class="country">
        <div title="0.187秒" class="bar">
          <div class="bar_inner fast" style="width:92%">
            
          </div>
        </div>
      </td>
      <td class="country">
        <div title="0.037秒" class="bar">
          <div class="bar_inner fast" style="width:95%">
            
          </div>
        </div>
      </td>
     
      <td>1天</td>
      <td>18-08-02 13:05</td>
    </tr>
 </table>  
STR;
        $ql = QueryList::rules(['ip' => ['td:eq(1)','text'],'port' => ['td:eq(2)','text']]);
        $ql->html($body)->range('#ip_list tr:gt(1)')->query()->getData(function($item){
            return self::checkProxyIp($item['ip'].':'.$item['port']);
        })->all();
    }

    protected static $_userAgent = [
        'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.101 Safari/537.36',
        'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/536.6 (KHTML, like Gecko) Chrome/20.0.1092.0 Safari/536.6',
        'Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/27.0.1453.94 Safari/537.36',
        'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/59.0.3071.109 Safari/537.36',
        'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.1 (KHTML, like Gecko) Chrome/22.0.1207.1 Safari/537.1',
        'Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:61.0) Gecko/20100101 Firefox/61.0',
        'Mozilla/5.0 (Windows NT 6.1; rv:2.0.1) Gecko/20100101 Firefox/4.0.1',
        'Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; rv:11.0) like Gecko',
        'Mozilla/5.0 (Windows NT 6.2; WOW64; rv:21.0) Gecko/20100101 Firefox/21.0',
        'Opera/9.80 (Windows NT 6.1; U; en) Presto/2.8.131 Version/11.11',
    ];

    //'ip:port'
    protected static $_proxy = [

    ];

}
